﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Security.Cryptography;
using System.Text;
using System.Net;
using System.IO;
using System.Runtime.Serialization.Json;

namespace WowDotNetAPI.Utilities
{
    public static partial class JsonUtility
    {

#if WINDOWS
        public static string GetJSON(string url)
        {
            WebClient WebClient = new WebClient();
            WebClient.Encoding = Encoding.UTF8;

            return GetJSON(WebClient, url);
        }

        public static string GetJSON(WebClient WebClient, string url)
        {
            return WebClient.DownloadString(url);
        }

        //JSON serialization - http://www.joe-stevens.com/2009/12/29/json-serialization-using-the-datacontractjsonserializer-and-c/
        public static T FromJSON<T>(string url) where T : class
        {
            WebClient WebClient = new WebClient();
            WebClient.Encoding = Encoding.UTF8;

            return FromJSON<T>(WebClient, url);
        }

 
        public static T FromJSON<T>(WebClient WebClient, string url) where T : class
        {
            using (MemoryStream stream = new MemoryStream(Encoding.UTF8.GetBytes(GetJSON(WebClient, url))))
            {
                DataContractJsonSerializer DataContractJsonSerializer = new DataContractJsonSerializer(typeof(T));
                return DataContractJsonSerializer.ReadObject(stream) as T;
            }
        }

        public static T FromJSON<T>(string url, string publicAuthKey, string privateAuthKey) where T : class
        {
            var client = new WebClient();
            client.Encoding = Encoding.UTF8;
            DateTime date = DateTime.Now.ToUniversalTime();
            client.Headers["Date"] = date.ToString();

            string stringToSign =
                "GET\n"
                + date.ToString("r") + "\n"
                + url + "\n";

            byte[] buffer = Encoding.UTF8.GetBytes(stringToSign);

            HMACSHA1 hmac = new HMACSHA1(Encoding.UTF8.GetBytes(privateAuthKey));

            string signature = Convert.ToBase64String(hmac.ComputeHash(buffer));

            client.Headers[HttpRequestHeader.Authorization]
                = "BNET " + publicAuthKey + ":" + signature;

            return FromJSON<T>(client, url);


            //HttpWebRequest req = WebRequest.Create(url) as HttpWebRequest;
            //DateTime date = DateTime.Now.ToUniversalTime();
            //req.Date = date;

            //string stringToSign =
            //    req.Method + "\n"
            //    + date.ToString("r") + "\n"
            //    + req.RequestUri.PathAndQuery + "\n";

            //byte[] buffer = Encoding.UTF8.GetBytes(stringToSign);

            //HMACSHA1 hmac = new HMACSHA1(Encoding.UTF8.GetBytes(privateAuthKey));

            //string signature = Convert.ToBase64String(hmac.ComputeHash(buffer));

            //req.Headers[HttpRequestHeader.Authorization]
            //    = "BNET " + publicAuthKey + ":" + signature;

            //return FromJSON<T>(req);
        }

        public static T FromJSON<T>(WebClient client, string url, string publicAuthKey, string privateAuthKey) where T : class
        {
            DateTime date = DateTime.Now.ToUniversalTime();
            client.Headers["Date"] = date.ToString();

            string stringToSign =
                "GET\n"
                + date.ToString("r") + "\n"
                + url + "\n";

            byte[] buffer = Encoding.UTF8.GetBytes(stringToSign);

            HMACSHA1 hmac = new HMACSHA1(Encoding.UTF8.GetBytes(privateAuthKey));

            string signature = Convert.ToBase64String(hmac.ComputeHash(buffer));

            client.Headers[HttpRequestHeader.Authorization]
                = "BNET " + publicAuthKey + ":" + signature;

            return FromJSON<T>(client, url);
        }
#endif

        public static string ToJSON<T>(T obj) where T : class
        {
            WebClient WebClient = new WebClient();
            WebClient.Encoding = Encoding.UTF8;

            return ToJSON<T>(WebClient, obj);
        }

        public static string ToJSON<T>(WebClient WebClient, T obj) where T : class
        {
            using (MemoryStream stream = new MemoryStream())
            {
                DataContractJsonSerializer DataContractJsonSerializer = new DataContractJsonSerializer(typeof(T));

                DataContractJsonSerializer.WriteObject(stream, obj);
                var bytes = stream.ToArray();
                return Encoding.UTF8.GetString(bytes,0,bytes.Length);
            }
        }

        public static T FromJSONStream<T>(StreamReader sr) where T : class
        {
            using (MemoryStream stream = new MemoryStream(Encoding.UTF8.GetBytes(sr.ReadToEnd())))
            {
                DataContractJsonSerializer DataContractJsonSerializer = new DataContractJsonSerializer(typeof(T));
                return DataContractJsonSerializer.ReadObject(stream) as T;
            }
        }

        public static T FromJSONString<T>(string str) where T : class
        {
            using (MemoryStream stream = new MemoryStream(Encoding.UTF8.GetBytes(str)))
            {
                DataContractJsonSerializer DataContractJsonSerializer = new DataContractJsonSerializer(typeof(T));
                return DataContractJsonSerializer.ReadObject(stream) as T;
            }
        }

    }
}
